package com.example.opengl.render.cubemap

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.opengl.GLES20
import android.opengl.GLES20.*
import android.opengl.GLUtils
import android.opengl.Matrix
import android.util.Log
import com.android.baselibrary.app.MainApplication
import com.example.opengl.R
import com.example.opengl.base.BufferHelper
import com.example.opengl.base.ShaderHelper
import com.example.opengl.base.TextResourceReader
import com.example.opengl.render.base.IDrawer
import java.nio.FloatBuffer

/**
 * @author: Mr.You
 * @create: 2023-08-07 15:01
 * @description: '
 **/
class CubeMapDrawer : IDrawer {
    private val r = 1.0f

    private val vertexCoords = floatArrayOf(
        //前面
        r, r, r,
        -r, r, r,
        -r, -r, r,
        r, -r, r,
        //后面
        r, r, -r,
        -r, r, -r,
        -r, -r, -r,
        r, -r, -r,
        //上面
        r, r, r,
        r, r, -r,
        -r, r, -r,
        -r, r, r,
        //下面
        r, -r, r,
        r, -r, -r,
        -r, -r, -r,
        -r, -r, r,
        //右面
        r, r, r,
        r, r, -r,
        r, -r, -r,
        r, -r, r,
        //左面
        -r, r, r,
        -r, r, -r,
        -r, -r, -r,
        -r, -r, r
    )

    private val textureCoords = floatArrayOf(
        //前面
        0f, 0f,
        1f, 0f,
        1f, 1f,
        0f, 1f,
        //后面
        0f, 0f,
        1f, 0f,
        1f, 1f,
        0f, 1f,
        //上面
        0f, 0f,
        1f, 0f,
        1f, 1f,
        0f, 1f,
        //下面
        0f, 0f,
        1f, 0f,
        1f, 1f,
        0f, 1f,
        //右面
        0f, 0f,
        1f, 0f,
        1f, 1f,
        0f, 1f,
        //左面
        0f, 0f,
        1f, 0f,
        1f, 1f,
        0f, 1f

    )

    private var vertexFloatBuffer: FloatBuffer? = null
    private var textureFloatBuffer: FloatBuffer? = null
    private var mProgram = -1
    private var vertexShader = -1
    private var textureShader = -1
    private var mvpMatrixPosition: Int = -1
    private var mRatio: Float = 1f
    private var mRotateAgree: Int = 0
    private var textureIds: IntArray? = null
    private val images = intArrayOf(
        R.mipmap.image1,
        R.mipmap.image2,
        R.mipmap.image3,
        R.mipmap.image4,
        R.mipmap.image5,
        R.mipmap.image6
    )


    override fun draw() {
        //清除深度缓存，颜色缓存
        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)

        transformMVP(mProgram, mRatio)

        glEnableVertexAttribArray(0)
        glEnableVertexAttribArray(1)

        transformMVP(mProgram, mRatio)

        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, vertexFloatBuffer)
        glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, textureFloatBuffer)

        glActiveTexture(GL_TEXTURE)

        drawSixImage()

        glDisableVertexAttribArray(0)
        glDisableVertexAttribArray(1)

    }

    private fun drawSixImage() {
        val count = 4
        Log.i("TAGasfd", "drawSixImage: ${textureIds?.size}")
        textureIds?.forEachIndexed { index, i ->
            val first = index * count
            glBindTexture(GL_TEXTURE_2D, i)
            glDrawArrays(GL_TRIANGLE_FAN, first, count)
        }
    }

    /**
     * 变换矩阵
     */
    private fun transformMVP(mProgram: Int, mRatio: Float) {
        val modelMatrix = getIdentityMatrix(16, 0)
        val viewMatrix = getIdentityMatrix(16, 0)
        val projectMatrix = getIdentityMatrix(16, 0)
        mRotateAgree = (mRotateAgree + 2) % 360
        Matrix.rotateM(modelMatrix, 0, mRotateAgree.toFloat(), -1f, -1f, 1f)
        Matrix.setLookAtM(viewMatrix, 0, 0f, 5f, 10f, 0f, 0f, 0f, 0f, 1f, 0f)
        Matrix.frustumM(projectMatrix, 0, -mRatio, mRatio, -1f, 1f, 3f, 20f)

        val tempMatrix = FloatArray(16)
        val mvpMatrix = FloatArray(16)
        Matrix.multiplyMM(tempMatrix, 0, viewMatrix, 0, modelMatrix, 0)
        Matrix.multiplyMM(mvpMatrix, 0, projectMatrix, 0, tempMatrix, 0)
        mvpMatrixPosition = glGetUniformLocation(mProgram, "mvpMatrix")
        glUniformMatrix4fv(mvpMatrixPosition, 1, false, mvpMatrix, 0)

    }

    override fun setTextureID(id: Int) {

    }

    override fun release() {

    }

    override fun setWorldSize(worldW: Int, worldH: Int) {
        glClearColor(0.1f, 0.2f, 0.3f, 0.4f);
         glEnable(GL_DEPTH_TEST)//开启深度测试,主要是避免被遮挡
        glViewport(0,0,worldW,worldH)
        mRatio = 1.0f * worldW / worldH



        initFloatBuffer()
        initShader()
        textureIds = loadTexture()
    }

    private fun loadTexture(): IntArray {
        val options = BitmapFactory.Options()
        options.inScaled = false
        val bitmapArray = arrayOfNulls<Bitmap>(images.size)
        val texturesId = IntArray(images.size)
        //生成纹理id
        glGenTextures(texturesId.size,texturesId,0)

        images.forEachIndexed { index, item ->
            bitmapArray[index] = BitmapFactory.decodeResource(MainApplication.mainApplication.resources, item, options)
            glBindTexture(GL_TEXTURE_2D, texturesId[index])
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
            GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmapArray[index], 0)
            glGenerateMipmap(GL_TEXTURE_2D)
            glBindTexture(GL_TEXTURE_2D, 0)
            bitmapArray[index]?.recycle()
        }
        return texturesId
    }


    //初始化着色器
    private fun initShader() {
        vertexShader =
            ShaderHelper.compileVertexShader(TextResourceReader.readTextFileFormResource(resourceId = R.raw.image_vertex_shader))
        textureShader =
            ShaderHelper.compileFragmentShader(TextResourceReader.readTextFileFormResource(resourceId = R.raw.image_fragment_shader))
        mProgram = ShaderHelper.linkProgram(vertexShader, textureShader)

        glUseProgram(mProgram)

    }

    //初始化顶点坐标和纹理坐标
    private fun initFloatBuffer() {

        vertexFloatBuffer = BufferHelper.getFloatBuffer(vertexCoords)

        textureFloatBuffer = BufferHelper.getFloatBuffer(textureCoords)

    }

    override fun setVideoSize(videoW: Int, videoH: Int) {


    }

    private fun getIdentityMatrix(size: Int, offset: Int): FloatArray {
        val matrix = FloatArray(size)
        Matrix.setIdentityM(matrix, offset);
        return matrix;
    }


}